"""
    TorrentBrowser plugin for XBMC
    Copyright (C) 2011-2012 Markus Langenoja
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
    Function [TBBrowser]
    -------------------
    * getItems(params) - Input params with either a 'page' or a 'id' key
      to obtain list of items to display in XBMC. I.E params = {'id':11}
"""
import re, sys
import TBTools
        
class TBBrowser(TBTools.TBTools): 
    __web__ = sys.modules[ "__main__" ].__web__
    __info__ = sys.modules[ "__main__" ].__info__
    __deb__ = sys.modules[ "__main__" ].__deb__
    __plugin__ = sys.modules[ "__main__" ].__plugin__
    __settings__ = sys.modules[ "__main__" ].__settings__
    __scraper__ = sys.modules[ "__main__" ].__scraper__
    
    __torrents_per_page__ = __info__['TORRENTSPERPAGE']
    __items_per_page__ = [5,10,15,20,25][int(__settings__.getSetting('itemsperpage'))]      
    
    def getItems(self, params):
        """
        Takes page number from XBMC or movie-id to fetch a list of items to either be further parsed
        or send directly to xbmc to be downloaded.
        """
        get = params.get
        action = get('action')
        
        # If a pagenumber from XBMC is given, compute following branch
        if action == 'search':
            if self.__deb__:
                print self.__plugin__ + '::DEBUG::TBBrowser::' + 'Searching movies using query: ' + str(get('searchstring'))
                
            return self.getSearchItems(params)
        
        elif action == 'get_formats':
            # If a torrent-id is given (currently only for PassThePopcorn), parse the page and return a dictionary
            # containing downloadUrl, Format, Filename and also if it is freeleech.      
            if self.__deb__:
                print self.__plugin__ + '::DEBUG::TBBrowser::' + 'Getting formats for movie-ID: ' + str(get('id'))
            
            return self.getFormatItems(params)
        
        elif action == 'get_movies':
            if self.__deb__:
                print self.__plugin__ + '::DEBUG::TBBrowser::' + 'Getting Movies from page: ' + str(get('page'))
        
            return self.getPageItems(params)
            
        # If neither page nor id is given, return error.
        else:
            print 'ERROR: Did not give useful information to TBBrowser.getItems'
            return
        
    def getFormatItems(self,params):
        get = params.get
        
        # Initiate itemList dict.
        itemList = {}
        i = 0
        
        if self.__deb__:
            print self.__plugin__ + '::DEBUG::TBBrowser::' + 'Running getFormats'
            
        if (not self.__info__['FORMATS']['formats']):
            # From TBSites, if site uses direct download from the movie-list, __info__['FORMATS']['formats'] would return False
            print self.__plugin__ + '::ERROR::TBBrowser::' + 'Something went wrong, site %s doesn\'t handle formats like gazelle' % self.__info__['SITE']
            return
        
        # Get data to parse the torrent-id page
        reget = self.__info__['FORMATS'].get
        url = reget('browseUrl') % (get('id'))
        regExp = reget('re')
        
        # Download and parse page using regexp
        raw = self.__web__.loginOpen(url)
        items = re.compile(regExp).findall(raw)
        
        if self.__deb__:
            print self.__plugin__ + '::DEBUG::Number of Items: ' + str(len(items))
        
        # Create dictionaries for each item containing information plus "freeleech" tag.
        for item in items:
            # Clean the dlstring and create the downloadurl
            url = self.__info__['BASEURL'] + '/' + self.replaceBadSigns(item[reget('dlurlindex')])
            # Cleans the Format-string from HTML tags and multi-spaces
            form = re.sub('<.+?>','',item[reget('formatindex')])
            form = re.sub('\s+',' ',form)
            # This sets the freeleech tag if found in format string, add it to begining of form (title)
            if re.search('.*[Ff]reeleech.*',item[reget('formatindex')]):
                form = '[FL] ' + form
            itemList[i] = {'folder':False,'downloadurl':url,'title':form,'filename':item[reget('filenameindex')],'scrape':False}
            i += 1
            
        return itemList
        
    def getSearchItems(self,params):
        get = params.get
        gets = self.__info__['SEARCH'].get
        
        # Obtain needed information for the search
        url = gets('url') + str(get('searchstring'))
        raw = self.__web__.loginOpen(url)
        pos = self.__info__['REGEXP']['pos']
        regExp = self.__info__['REGEXP']['re']
        
        # This searches the page using regexp matching site unique "Not found"
        if re.search(gets('re'),raw):
            ''' Call TBXbmc and show a OK dialog '''
            message = ['Sorry, nothing matched for', get('searchstring')]
            self.showOK('Nothing Found', message)
            return
            
        # If the site redirects to the torrent site instead of showing results
        # this will check for it and rerun getItems with the torrent ID instead
        # Currently this is implemented purely with PassThePopcorn in mind.
        if gets('check'):
            if (not re.search(gets('check'),raw)):
                ''' If the search is a direct match, redo but with ID '''
                print 'Direct Hit, you sank the %s battleship!' % (get('searchstring'))
                searchID = re.compile(gets('idregexp')).findall(raw)
                params = {'id':searchID[0],'action':'get_formats'}
                return self.getItems(params)
            
        # Find items and build the itemlist
        items = re.compile(regExp).findall(raw)
        itemList = self.buildList(0, len(items), items, pos)
        return itemList
    
    def getPageItems(self,params):
        get = params.get
        # Call getPositions, returns a dictionary if not on two pages, else a tuple with dictionarys
        positions = self.getPositions(get('page'),get('category'))
        
        # Obtain RegExp information
        reget = self.__info__['REGEXP'].get
        regExp = reget('re')
        pos = reget('pos')
        print reget
        print positions
        # Obtain data and build list of items containing (id, title, imdbid) in a dictionary for each item
        # Depending on if the "positions" return as a tuple, run over two pages, else just one
        if type(positions) == tuple:
            raw1 = self.__web__.loginOpen(positions[0]['url'])
            raw2 = self.__web__.loginOpen(positions[1]['url'])
            items1 = re.compile(regExp).findall(raw1)
            items2 = re.compile(regExp).findall(raw2)
            itemList = self.buildList(positions[0]['start'], positions[0]['stop'], items1, pos)
            itemList = self.buildList(len(itemList)+positions[1]['start'], len(itemList)+positions[1]['stop'], items2, pos, itemList=itemList)
        else:
            raw = self.__web__.loginOpen(positions['url'])
            items = re.compile(regExp).findall(raw)
            itemList = self.buildList(positions['start'], positions['stop'], items, pos)
        
        return itemList
    
    def buildList(self, start, stop, items, pos, itemList={}):
        """
        Modulization for the page-part above. Builds a new itemList if non specified (default behaviour)
        and appends the itemList if specified.
        """
        for o in xrange(int(len(itemList)+start),int(len(itemList)+stop)):
            item = items[o]
            # If new list, set first value to 0 as the id-parsing part does.
            if len(itemList) == 1:
                i = 0
            else:
                i = len(itemList) +1
            # Start the list
            itemList[i] = {'id':item[pos[0]],'title':item[pos[1]],'scrape':True}
            # If the data contains an IMDB-ID, get this.
            if pos[2]:
                itemList[i]['imdb'] = item[pos[2]]
            # If the data contains the downloadUrl, provide it else provide isFolder
            if pos[3]:
                itemList[i]['filename'] = item[pos[1]]
                itemList[i]['downloadurl'] = self.__info__['BASEURL'] + '/' + self.replaceBadSigns(item[pos[3]])
                itemList[i]['folder'] = False
            else:
                itemList[i]['folder'] = True
                
        return itemList
    
    def getPositions(self,page,category):
        """
        This function calculates how and where to retrieve items from the torrent site.
        """
        # Get basic browseUrl
        print 'DEBUG::: PAGE: %s CATEGORY: %s' % (page,category)
        urlBase = self.__info__[category]
        pageUrl = urlBase + self.__info__['NEXTPAGE']['addon']
        
        # Sets correct number of items to show if settings are to high for site.
        if self.__items_per_page__ >= self.__torrents_per_page__:
            __nmbritems__ = self.__torrents_per_page__
        else:
            __nmbritems__ = self.__items_per_page__
        if self.__deb__:
            print self.__plugin__ + '::DEBUG::Number of Items: ' + str(__nmbritems__)
                    
        # Calculate positions using current XBMC-page and number of items showing per page in XBMC.
        endpos = int(page) * int(__nmbritems__)
        pos = int(endpos) - int(__nmbritems__)
        
        # Sets URL's appropriate to positions
        # If pos is within limits of first browser page
        if (pos >= 0) and (pos <= self.__torrents_per_page__):
            firstUrl = urlBase
            # If endpos isn't located on the first page, set the secondUrl to next page
            if (endpos / self.__torrents_per_page__ > 0):
                secondUrl = pageUrl + str(2 + self.__info__['NEXTPAGE']['adj'])
        else:
            # Decide which page number and adjust it according to TBSites, then set firstUrl.
            nr = pos/self.__torrents_per_page__
            pageNr = nr + 1 + self.__info__['NEXTPAGE']['adj']
            firstUrl = pageUrl + str(pageNr)
            # If endpos isn't on the same page AND the modulus of endpos and __torrent_per_page__ 
            # isn't 0 (endpos being the last entry on page). Set secondPage to next url in place.
            if (endpos / self.__torrents_per_page__ > nr) and (endpos % self.__torrents_per_page__  != 0):
                secondUrl = pageUrl + str(pageNr + 1)
                
        # Instead of having sets of else inside the if/else clause above, set secondUrl to None if
        # it hasn't already been set.
        try:
            secondUrl
        except: secondUrl = None

        # Build tuple if secondUrl isn't None, first value being the first page and second value
        # being the second page.
        if secondUrl:
            positions = ({'url':firstUrl,'start':pos % self.__torrents_per_page__,'stop':self.__torrents_per_page__},{'url':secondUrl,'start':0,'stop':endpos % self.__torrents_per_page__})
        else:
            # If endpos is located at the end of the page, set it to end of page, otherwise
            # calculate where the end is.
            if (endpos % self.__torrents_per_page__ == 0):
                end = self.__torrents_per_page__
            else:
                end = endpos % self.__torrents_per_page__
            positions = {'url':firstUrl,'start':pos % self.__torrents_per_page__,'stop':end}
                
        if self.__deb__:
            print self.__plugin__ + '::DEBUG::TBBrowser::Positions:\n' + str(positions)
            
        return positions